package proxy;

import sun.misc.ProxyGenerator;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class AOPHandle implements InvocationHandler {
  ISayHelloWorld iSayHelloWorld;

  public AOPHandle(ISayHelloWorld iSayHelloWorld) {
    this.iSayHelloWorld = iSayHelloWorld;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 方法返回值
    System.out.println("前置代理");
    // 反射调用方法
    Object ret = method.invoke(iSayHelloWorld, args);
    // 声明结束
    System.out.println("后置代理");
    // 返回反射调用方法的返回值
    return ret;
  }

  public static void main(String[] args) throws IOException {
    final ISayHelloWorld sayHelloWorld = new ManSayHelloWorld();

    AOPHandle handle = new AOPHandle(sayHelloWorld);
    ISayHelloWorld i =
        (ISayHelloWorld)
            Proxy.newProxyInstance(
                ISayHelloWorld.class.getClassLoader(),
                ISayHelloWorld.class.getInterfaces(),
                new InvocationHandler() {
                  @Override
                  public Object invoke(Object proxy, Method method, Object[] args)
                      throws Throwable {
                    if (method.getName().equals("doIt")) {
                      System.out.println("doIt前置代理66666666666");

                      Object ret = method.invoke(sayHelloWorld, args);
                      return ret;
                    }

                    // 方法返回值
                    System.out.println("前置代理111");
                    // 反射调用方法
                    Object ret = method.invoke(sayHelloWorld, args);
                    // 声明结束
                    System.out.println("后置代理1111");
                    // 返回反射调用方法的返回值
                    return ret;
                  }
                });
    i.say();
    i.doIt();
    i.rest();

    String proxyName = "com.sun.proxy.$Proxy0";
    Class<?>[] interfaces = ManSayHelloWorld.class.getInterfaces();
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, 17);
    FileOutputStream fileOutputStream =
        new FileOutputStream(
            new File(
                AOPHandle.class.getClassLoader().getResource("").getPath() + "/$Proxy0.class"));
    fileOutputStream.write(proxyClassFile);
  }
}
